package com.ibm.framework.exception.utils;

import static com.ibm.framework.exception.model.ConfigConstant.LINE_SEPARATOR;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 异常工具类
 * 
 * @author gan jianfeng
 * 
 */
public class CommonExceptionUtils {

    /**
     * Build a message for the given base message and root cause.
     * 
     * @param message the base message
     * @param cause the root cause
     * @return the full exception message
     */
    public static String buildMessage(String message, Throwable cause) {
        if (cause != null) {
            StringBuilder sb = new StringBuilder();
            if (message != null) {
                sb.append(message).append("; ");
            }
            sb.append("nested exception is ").append(cause);
            return sb.toString();
        } else {
            return message;
        }
    }

    /**
     * 得到指定异常的rootCause
     * 
     * @param ex 异常原因
     * @return rootCause
     */
    public static Throwable getRootCause(Throwable ex) {
        Throwable rootCause = null;
        Throwable cause = ex.getCause();
        while (cause != null && cause != rootCause) {
            rootCause = cause;
            cause = cause.getCause();
        }
        return rootCause;
    }

    /**
     * 得到指定异常的rootCause,如果没有rootCause,则把参数指定的异常作为rootCause, 以免返回null
     * 
     * @param ex 异常
     * @return 指定异常的rootCause
     */
    public static Throwable getMostSpecificCause(Throwable ex) {
        Throwable rootCause = getRootCause(ex);
        return (rootCause != null ? rootCause : ex);
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉 获取异常堆栈信息
     * 
     * @param ex 异常
     * @return 异常堆栈信息
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String getExceptionStackTrace(Throwable ex) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        pw.close();
        return sw.toString();
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉 获取最详细的异常信息
     * 
     * @param ex 异常原因
     * @return 最详细的异常信息
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String getMostSpecificCauseMessageInfo(Throwable ex) {
        // get rootCause of exception
        /** 得到根异常 */
        Throwable rootCause = getMostSpecificCause(ex);
        /** 得到Stack trace的elements */
        StackTraceElement[] elements = rootCause.getStackTrace();

        String rootException = rootCause.getClass().getName();
        String rootExceptionMsg = rootCause.getLocalizedMessage();
        /** 抛出根异常的类 */
        String rootCauseSpotClass = elements[0].getClassName();
        /** 抛出根异常的方法 */
        String rootCauseSpotMethod = elements[0].getMethodName();
        /** 抛出根异常的行号 */
        int rootCauseSpotLine = elements[0].getLineNumber();

        StringBuilder sbdr = new StringBuilder(LINE_SEPARATOR);

        sbdr.append("[Root Exception]: ").append(rootException).append(LINE_SEPARATOR)
                .append("[Root Exception Message]: ").append(rootExceptionMsg).append(LINE_SEPARATOR)
                .append("[Root Exception throwed on]: ").append(rootCauseSpotClass).append(".")
                .append(rootCauseSpotMethod).append("  Line:").append(rootCauseSpotLine);

        return sbdr.toString();
    }

}
